home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
math
/
alged34.zip
/
ALGEDSRC.ZIP
/
ALGSHOW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-06
|
15KB
|
583 lines
/*--------------------------------------------------------------------
Alged: Algebra Editor henckel@vnet.ibm.com
Copyright (c) 1994 John Henckel
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies.
*/
#include "alged.h"
#include <alloc.h>
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The following functions relate to displaying expressions on the
screen.
*/
/*-----------------------------------------------------------------
twirl - this spins a little status indicator on the bottom
of the display to reassure the user in long calculations.
*/
void twirl(void) {
static char c[] = "/-\\|";
static int i=0;
gotoxy(5,ti.screenheight);
putch(c[i]);
if (++i > 3) i=0;
}
/*--------------------------------------------------------------------
debug dump
*/
void dumpnode(node *p,int tab) {
int i;
for (i=0; i<tab; ++i) putch(' ');
cprintf("%p %d %d (%d %d) %d '%s'\r\n",p,p->kind,p->nump,
p->px,p->py,p->sy,p->name);
for (i=0; i<p->nump; ++i)
dumpnode(p->parm[i],tab+2);
}
/*--------------------------------------------------------------------
re compute size of each node
*/
void resize(node *p,int ppr) {
double x;
int mpr,i;
mpr = pr[p->kind];
p->ay = 0;
switch (p->kind) {
case NUM:
x = fabs(p->value);
p->name[0] = 0;
if (p->value<0) strcat(p->name,"-");
if (x==M_PI) strcat(p->name,piname);
else if (x==M_E) strcat(p->name,ename);
else if (x==HUGE_VAL) strcat(p->name,infname);
else if (ch8 && x==0.5) strcat(p->name,halfname);
else if (ch8 && x==0.25) strcat(p->name,qtrname);
else sprintf(p->name,"%1.15G",p->value);
p->sy=1;
p->sx=strlen(p->name);
if (!point && strchr(p->name,'.')) *strchr(p->name,'.') = ',';
break;
case BAD:
strcpy(p->name,errname); /* fall thru */
case VAR:
p->sy=1;
p->sx=strlen(p->name);
break;
case EQU:
case ADD:
case SUB:
p->sx = 3;
if (mpr<ppr) p->sx += 2; /* parens */
resize(p->lf,mpr);
resize(p->rt,mpr+1); /* +1 = a hack */
p->sy = max(p->lf->sy,p->rt->sy);
p->sx += p->lf->sx + p->rt->sx;
strcpy(p->name,kname[p->kind]);
break;
case MUL:
p->sx = 1;
if (mpr<ppr) p->sx += 2; /* parens */
resize(p->lf,mpr);
resize(p->rt,mpr+1); /* +1 = a hack */
p->sy = max(p->lf->sy,p->rt->sy);
p->sx += p->lf->sx + p->rt->sx;
strcpy(p->name,kname[p->kind]);
break;
case DIV:
resize(p->lf,1); /* 1 = div suppresses parens */
resize(p->rt,1);
p->sx = max(p->lf->sx,p->rt->sx) + 2;
p->sy = p->lf->sy + p->rt->sy + 1;
p->ay = p->lf->sy - p->rt->sy;
if (p->ay <0) p->ay--;
p->ay /= 2;
if (mpr<ppr) p->sx += 2; /* parens */
strcpy(p->name,kname[p->kind]);
break;
case EXP:
resize(p->lf,mpr+1);
resize(p->rt,mpr);
p->sx = p->lf->sx + p->rt->sx;
p->sy = p->lf->sy + p->rt->sy;
p->ay = p->rt->sy - p->lf->sy;
if (p->ay >0) p->ay++;
p->ay /= 2;
if (mpr<ppr) p->sx += 2; /* parens */
strcpy(p->name,kname[p->kind]);
break;
case FUN:
p->sx = strlen(p->name) + 1; /* 2 parens JDH check this! */
p->sy = 0;
for (i=0; i<p->nump; ++i) {
resize(p->parm[i],mpr);
setmax(p->sy,p->parm[i]->sy);
p->sx += 1 + p->parm[i]->sx; /* 1 comma */
}
break;
default:
printf(msg[14]);
pause;
}
}
/*--------------------------------------------------------------------
leftpar - print a left parenthesis
*/
void leftpar(int h) {
int i;
if (h<2) {
putch('('); return; }
relxy(0,-h/2);
putch(ulc);
for (i=0; i<h-2; ++i) {
relxy(-1,1);
putch(vline);
}
relxy(-1,1);
putch(llc);
}
/*--------------------------------------------------------------------
rightpar - print a right parenthesis
*/
void rightpar(int h) {
int i;
if (h<2) {
putch(')'); return; }
relxy(0,-h/2);
putch(urc);
for (i=0; i<h-2; ++i) {
relxy(-1,1);
putch(vline);
}
relxy(-1,1);
putch(lrc);
}
/*-----------------------------------------------------------------
fix attributes
*/
int fixattr(node *p) {
gettextinfo(&ti);
if (p==src) textattr(bold1);
return ti.attribute;
}
#define seen (x > 0 && x < ti.screenwidth)
/*--------------------------------------------------------------------
print expression
*/
void show(node *p,int ppr,int x,int y) {
int mpr,i,z,s0,s1,attr;
mpr = pr[p->kind];
if (yadj) y = y + p->ay; /* adjust y */
gotoxy(x,y);
attr=fixattr(p); /* save old attribute */
switch (p->kind) {
case NUM:
case BAD:
case VAR:
p->px = x; p->py = y;
i = strlen(p->name); z = 0;
if (x > ti.screenwidth) break;
if (i+x > ti.screenwidth) i = ti.screenwidth - x;
if (x < 1) { gotoxy(1,y); z = -x; }
if (z < i) cprintf("%.*s",i-z,p->name+z);
break;
case EQU:
case ADD:
case SUB:
if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
show(p->lf,mpr,x,y);
x += p->lf->sx + 1;
gotoxy(x-1,y);
fixattr(p);
if (seen) cprintf(" %s ",kname[p->kind]);
show(p->rt,mpr+1,x+2,y);
p->px = x; p->py = y;
if (mpr<ppr) {
x += 2+p->rt->sx;
gotoxy(x,y);
fixattr(p);
if (seen) rightpar(p->sy); /* parens */
}
break;
case MUL:
if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
show(p->lf,mpr,x,y);
x += p->lf->sx;
gotoxy(x,y);
fixattr(p);
if (seen) cputs(ch8 ? kname[p->kind] : "*");
show(p->rt,mpr+1,x+1,y);
p->px = x; p->py = y;
if (mpr<ppr) {
x += 1+p->rt->sx;
gotoxy(x,y);
fixattr(p);
if (seen) rightpar(p->sy); /* parens */
}
break;
case DIV:
if (seen) for (i=0; i<p->sx; ++i) {
if (x+i < ti.screenwidth) putch(hline);
}
else if (x<1 && 0<(i=x+p->sx)) {
gotoxy(1,y); while (--i) putch(hline);
}
p->px = x; p->py = y;
if (mpr<ppr) {
gotoxy(x,y);
if (seen) leftpar(p->sy); /* parens */
}
show(p->lf,1,x + (p->sx - p->lf->sx)/2,
y - (p->lf->sy + 1)/2);
fixattr(p);
show(p->rt,1,x + (p->sx - p->rt->sx)/2,
y + (p->rt->sy + 2)/2);
if (mpr<ppr) {
x+=p->sx-1;
gotoxy(x,y);
fixattr(p);
if (seen) rightpar(p->sy); /* parens */
}
break;
case EXP:
if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; } /* parens */
show(p->rt,mpr ,x + p->lf->sx,y - (p->rt->sy + 1)/2);
fixattr(p);
show(p->lf,mpr+1,x, y + (p->lf->sy + 0)/2);
p->px = x + p->lf->sx - 1;
p->py = y - 1;
if (mpr<ppr) {
x += p->sx-2;
gotoxy(x,y);
fixattr(p);
if (seen) rightpar(p->sy); /* parens */
}
break;
case FUN:
p->px = x; p->py = y;
if (seen) {
cputs(p->name);
leftpar(p->sy);
}
x += strlen(p->name) + 1;
for (i=0; ; ) {
show(p->parm[i],mpr,x,y);
x += p->parm[i]->sx;
gotoxy(x,y);
fixattr(p);
if (++i >= p->nump) break;
if (seen) putch(comma);
++x;
}
if (seen) rightpar(p->sy); /* parens */
break;
default:
printf(msg[15]);
pause;
}
textattr(attr);
}
/*-----------------------------------------------------------------
This test the integrity of the heap and returns the amount of
space USED.
*/
long heapused() {
struct heapinfo hi; long t=0;
if (heapcheck()<0) {
printf(msg[28]); pause;
return -1;
}
hi.ptr=NULL;
while (heapwalk(&hi)==2)
if (hi.in_use) t+=hi.size;
return t;
}
/*-----------------------------------------------------------------
display menu
if the corner is 200, then no redraw is necessary.
*/
void show_menu(void) {
int i,j,x=999,y=0; time_t t;
textattr(mcolor);
gettext(1,ti.screenheight,1,ti.screenheight,&i);
if ((i&255)!=200 || rand()<6000) {
for (i=0; i<numm; ++i) if (menu[i].name[0]!='.') {
if (x > ti.screenwidth-mwidth+1) { x=1; ++y; }
menu[i].x = x;
menu[i].y = y;
gotoxy(x,y);
if (x>1) putch(vline); else putch(' ');
cputs(menu[i].name);
for (j=strlen(menu[i].name)+1; j<mwidth; ++j) putch(' ');
x+=mwidth;
}
mheight = y+1; /* number of lines used by the menu */
relxy(-1,0);
for (x=wherex(); x>1 && x<=ti.screenwidth; ++x)
if (x%mwidth!=1) putch(' '); else putch(vline);
/* MAKE THE BOX AROUND THE FORMULA */
if (ch8) {
gotoxy(1,y+1);
putch(201);
for (i=2; i<ti.screenwidth; ++i) putch(205);
putch(187);
gotoxy(1,ti.screenheight);
putch(200);
for (i=2; i<ti.screenwidth; ++i) putch(205);
putch(188);
}
gotoxy((ti.screenwidth-strlen(top))/2,mheight);
cputs(top);
}
if (ch8)
for (i=mheight+1; i<ti.screenheight; ++i) {
gotoxy(1,i); putch(186); gotoxy(ti.screenwidth,i); putch(186);
}
gotoxy(5,ti.screenheight);
t=time(0);
cprintf(" %.5s %2lu%% ",ctime(&t)+11,100*heapused()/heapsz);
cputs(bottom);
gotoxy(2,ti.screenheight-1);
}
/*-----------------------------------------------------------------
Check for menu select
*/
int selection(int x, int y) {
int i;
for (i=0; i<numm; ++i)
if (x>=menu[i].x && x<menu[i].x+mwidth && y==menu[i].y)
return menu[i].fid;
if (y==mheight) return PRV;
if (x==1) return PPL;
if (x==ti.screenwidth) return PPR;
if (y==ti.screenheight) return NXT;
return -1;
}
/*--------------------------------------------------------------------
display expressions (as many as possible) starting at p.
*/
void display(node *p) {
int x,y,i,ts=0;
if (tgt) {
resize(tgt,0);
ts = ti.screenheight/2;
if (ts > tgt->sy) ts=tgt->sy;
}
y=mheight+1;
numsee = 0;
while (p) {
resize(p,0);
x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
if (p->msg && y+ts+1+p->sy < ti.screenheight) {
gotoxy(1,y);
textattr(bold2); cprintf("%s",p->msg); textattr(norm);
y = wherey()-1;
}
y += p->sy+1;
if (y+ts >= ti.screenheight) break;
show(p,0,x,y - (p->sy+1)/2);
p = p->next;
++numsee;
}
if (!p && y+ts+1 < ti.screenheight) { /* end of list */
gotoxy((ti.screenwidth-strlen(endlist))/2,y+1);
cputs(endlist);
}
if (ts) {
x = (ti.screenwidth-2 - tgt->sx)/2 + 2 + panx;
y = ti.screenheight - ts + tgt->sy/2;
show(tgt,0,x,y);
textattr(mcolor);
gotoxy(2,ti.screenheight-ts-1);
for (i=2; i<ti.screenwidth; ++i) putch(hline);
gotoxy(4,ti.screenheight-ts-1);
cputs(keyname);
textattr(norm);
}
}
/*--------------------------------------------------------------------
debug print out -- return 0 if 'g' is pressed
*/
int debug(node *p) {
int x,y;
window(1,mheight+1,ti.screenwidth,ti.screenheight-1);
textattr(norm);
clrscr();
cprintf(msg[35]);
resize(p,0);
x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
y = ti.screenheight/2;
show(p,0,x,y);
window(1,1,ti.screenwidth,ti.screenheight);
return 'g'!=getch();
}
/*-----------------------------------------------------------------
which node is pointed to?
*/
node *find_node(node *p,int x,int y) {
int i; node *t;
switch (p->kind) {
case ADD: case MUL: case EQU:
case EXP: case SUB:
if (x == p->px && y==p->py) {
return p;
}
break;
case DIV:
if (x >= p->px && y==p->py &&
x < (p->px+p->sx)) {
return p;
}
break;
case FUN:
if (x >= p->px && y==p->py &&
x < (p->px+strlen(p->name))) {
return p;
}
break;
default:
if (x >= p->px && y==p->py &&
x < (p->px + p->sx)) {
return p;
}
}
for (i=0; i<p->nump; ++i)
if (!!(t=find_node(p->parm[i],x,y))) return t;
return NULL;
}
/*-----------------------------------------------------------------
prompt the user for oneline input
return value is non-reuseable!
*/
char *keyin(char *pmt) {
static char buf[160]; int i;
window(1,ti.screenheight-4,ti.screenwidth-1,ti.screenheight-1);
textattr(norm);
clrscr();
cputs(pmt);
cputs("\r\n");
buf[0] = sizeof buf - 7;
cgets(buf); buf[0]=buf[1]=' ';
window(1,1,ti.screenwidth,ti.screenheight);
if (!buf[2]) strcpy(buf+2,"*.ae");
i = strlen(buf);
while (strchr(buf+2,'*') || strchr(buf+2,'?') || buf[i-1]=='\\') {
clrscr();
memmove(buf+7,buf+2,i-1);
memcpy(buf,"dir /w ",7);
printf("'%s'\n",buf);
system(buf);
printf("%s",pmt);
gets(buf+2);
i = strlen(buf);
}
if (i<4 || !strchr(buf+i-4,'.')) strcat(buf,".ae");
return buf+2;
}
/*-----------------------------------------------------------------
show help file
*/
void showhelp(char *argv0) {
FILE *f;
int i,c=0;
static char s[85];
/* strcpy(s,argv0);
strcpy(s+strlen(argv0)-4,lang); don't use exe path */
i=*argv0;
strcpy(s,"alged");
strcat(s,lang);
strcat(s,".hlp");
f = fopen(s,"r");
if (!f) { printf(msg[16],s);
pause; return;
}
textattr(norm);
clrscr();
i = ti.screenheight-1;
while (!feof(f)) {
printf(fgets(s,80,f));
if (!--i) {
i = ti.screenheight-4;
while (!(c=getch()));
if (c==27) break;
}
}
if (c!=27) getch();
fclose(f);
}
/*-----------------------------------------------------------------
load menu def
*/
int loadmenu(char *argv0) {
FILE *f;
int i,c=0;
static char s[85];
i=*argv0;
/*
strcpy(s,argv0);
strcpy(s+strlen(argv0)-4,lang); don't use exe path */
strcpy(s,"alged");
strcat(s,lang);
strcat(s,".mnu");
f = fopen(s,"r");
if (!f) { printf(msg[16],s);
pause; return 1;
}
for (i=0; i<MAXM; ++i) msg[i]="[message not found]\n";
while (!feof(f)) {
fscanf(f,"%s",s);
if (!strcmp(s,"item")) {
c=0;
fscanf(f," \"%[^\"]\" %d %d",s,&i,&c);
if (!c) fscanf(f," '%c'",&c);
strcpy(menu[numm].name,s);
menu[numm].fid=i;
menu[numm++].hot=c;
}
else if (*s==';') {
fgets(s,sizeof s,f);
}
else if (!strcmp(s,"bottom")) {
fscanf(f," \"%[^\"]\"",bottom);
}
else if (!strcmp(s,"key")) {
fscanf(f," \"%[^\"]\"",keyname);
}
else if (!strcmp(s,"top")) {
fscanf(f," \"%[^\"]\"",top);
}
else if (!strcmp(s,"endlist")) {
fscanf(f," \"%[^\"]\"",endlist);
}
else if (!strcmp(s,"width")) {
fscanf(f,"%d",&mwidth);
}
else if (!strcmp(s,"msg")) {
fscanf(f,"%d ",&i);
fgets(s,sizeof s,f);
c = strlen(s);
if (s[c-2]=='$') s[c-2]=0;
if (i>=0&&i<MAXM) {
msg[i]=malloc(strlen(s)+1);
strcpy(msg[i++],s);
}
}
}
fclose(f);
return 0;
}